const db = require('../models');
const Post = db.Post;
const User = db.User;
const Tag = db.Tag;
const { Op } = require('sequelize');
const slugify = require('slugify');
const { success, error } = require('../utils/response');

// 获取所有文章
exports.getAllPosts = async (req, res) => {
  try {
    let { page = 1, limit = 10, status, search, tagId } = req.query;
    page = parseInt(page);
    limit = parseInt(limit);
    
    const where = {};
    
    // 如果不是管理员请求，只返回已发布的文章
    if (!req.user || !req.user.isAdmin) {
      where.status = 'published';
    } else if (status) {
      where.status = status;
    }
    
    // 搜索功能
    if (search) {
      where[Op.or] = [
        { title: { [Op.like]: `%${search}%` } },
        { content: { [Op.like]: `%${search}%` } }
      ];
    }
    
    // 标签过滤
    const include = [
      {
        model: User,
        as: 'author',
        attributes: ['id', 'username', 'email', 'fullName', 'avatar']
      }
    ];
    
    if (tagId) {
      include.push({
        model: Tag,
        as: 'tags',
        where: { id: tagId },
        through: { attributes: [] }
      });
    } else {
      include.push({
        model: Tag,
        as: 'tags',
        through: { attributes: [] }
      });
    }
    
    const { count, rows } = await Post.findAndCountAll({
      where,
      include,
      order: [['createdAt', 'DESC']],
      limit,
      offset: (page - 1) * limit,
      distinct: true
    });
    
    return res.status(200).json(success({
      posts: rows,
      totalPosts: count,
      totalPages: Math.ceil(count / limit),
      currentPage: page
    }, '获取文章列表成功'));
  } catch (err) {
    console.error('获取文章列表失败:', err);
    return res.status(500).json(error('获取文章列表失败', 500));
  }
};

// 通过ID获取文章
exports.getPostById = async (req, res) => {
  try {
    const { id } = req.params;
    
    const post = await Post.findByPk(id, {
      include: [
        {
          model: User,
          as: 'author',
          attributes: ['id', 'username', 'email', 'fullName', 'avatar']
        },
        {
          model: Tag,
          as: 'tags',
          through: { attributes: [] }
        }
      ]
    });
    
    if (!post) {
      return res.status(404).json(error('文章不存在', 404));
    }
    
    // 如果文章不是已发布状态，且请求者不是作者或管理员，则拒绝访问
    if (post.status !== 'published' && 
        (!req.user || (req.user.id !== post.userId && !req.user.isAdmin))) {
      return res.status(403).json(error('无权访问此文章', 403));
    }
    
    // 增加阅读次数
    await post.increment('viewCount');
    
    return res.status(200).json(success(post, '获取文章成功'));
  } catch (err) {
    console.error('获取文章详情失败:', err);
    return res.status(500).json(error('获取文章详情失败', 500));
  }
};

// 创建文章
exports.createPost = async (req, res) => {
  try {
    const { title, content, summary, featuredImage, status, tags } = req.body;
    
    if (!title || !content) {
      return res.status(400).json(error('标题和内容不能为空', 400));
    }
    
    // 生成slug
    let slug = slugify(title, {
      lower: true,
      strict: true
    });
    
    // 检查slug是否已存在，如果存在则添加随机字符串
    const existingPost = await Post.findOne({ where: { slug } });
    if (existingPost) {
      slug = `${slug}-${Date.now().toString().slice(-6)}`;
    }
    
    // 创建文章
    const post = await Post.create({
      title,
      slug,
      content,
      summary: summary || null,
      featuredImage: featuredImage || null,
      status: status || 'draft',
      userId: req.user.id,
      publishedAt: status === 'published' ? new Date() : null
    });
    
    // 如果有标签，关联标签
    if (tags && tags.length > 0) {
      await post.setTags(tags);
    }
    
    // 返回创建的文章（包括关联的标签）
    const createdPost = await Post.findByPk(post.id, {
      include: [
        {
          model: User,
          as: 'author',
          attributes: ['id', 'username', 'email', 'fullName', 'avatar']
        },
        {
          model: Tag,
          as: 'tags',
          through: { attributes: [] }
        }
      ]
    });
    
    return res.status(201).json(success(createdPost, '文章创建成功', 201));
  } catch (err) {
    console.error('创建文章失败:', err);
    return res.status(500).json(error('创建文章失败', 500));
  }
};

// 更新文章
exports.updatePost = async (req, res) => {
  try {
    const { id } = req.params;
    const { title, content, summary, featuredImage, status, tags } = req.body;
    
    const post = await Post.findByPk(id);
    
    if (!post) {
      return res.status(404).json(error('文章不存在', 404));
    }
    
    // 检查是否有权限更新文章（作者或管理员）
    if (post.userId !== req.user.id && !req.user.isAdmin) {
      return res.status(403).json(error('无权更新此文章', 403));
    }
    
    // 如果标题已更改，需要更新slug
    let slug = post.slug;
    if (title && title !== post.title) {
      slug = slugify(title, {
        lower: true,
        strict: true
      });
      
      // 检查slug是否已存在（排除当前文章）
      const existingPost = await Post.findOne({
        where: {
          slug,
          id: { [Op.ne]: id }
        }
      });
      
      if (existingPost) {
        slug = `${slug}-${Date.now().toString().slice(-6)}`;
      }
    }
    
    // 如果状态从草稿变为已发布，设置发布时间
    const publishedAt = 
      post.status !== 'published' && status === 'published'
        ? new Date()
        : post.publishedAt;
    
    // 更新文章
    await post.update({
      title: title || post.title,
      slug,
      content: content || post.content,
      summary: summary !== undefined ? summary : post.summary,
      featuredImage: featuredImage !== undefined ? featuredImage : post.featuredImage,
      status: status || post.status,
      publishedAt
    });
    
    // 更新标签关联
    if (tags && Array.isArray(tags)) {
      await post.setTags(tags);
    }
    
    // 返回更新后的文章
    const updatedPost = await Post.findByPk(id, {
      include: [
        {
          model: User,
          as: 'author',
          attributes: ['id', 'username', 'email', 'fullName', 'avatar']
        },
        {
          model: Tag,
          as: 'tags',
          through: { attributes: [] }
        }
      ]
    });
    
    return res.status(200).json(success(updatedPost, '文章更新成功'));
  } catch (err) {
    console.error('更新文章失败:', err);
    return res.status(500).json(error('更新文章失败', 500));
  }
};

// 删除文章
exports.deletePost = async (req, res) => {
  try {
    const { id } = req.params;
    
    const post = await Post.findByPk(id);
    
    if (!post) {
      return res.status(404).json(error('文章不存在', 404));
    }
    
    // 检查是否有权限删除文章（作者或管理员）
    if (post.userId !== req.user.id && !req.user.isAdmin) {
      return res.status(403).json(error('无权删除此文章', 403));
    }
    
    // 删除文章（软删除）
    await post.destroy();
    
    return res.status(200).json(success(null, '文章删除成功'));
  } catch (err) {
    console.error('删除文章失败:', err);
    return res.status(500).json(error('删除文章失败', 500));
  }
};

/**
 * 前台文章列表分页
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
exports.getPublicPosts = async (req, res) => {
  try {
    const { page = 1, pageSize = 10, categoryId, tag } = req.query;
    const currentPage = parseInt(page);
    const limit = parseInt(pageSize);
    
    const where = {
      status: 'published' // 只显示已发布的文章
    };
    
    // 构建查询条件
    if (categoryId) {
      where.categoryId = categoryId;
    }
    
    // 构建关联查询
    const include = [
      {
        model: User,
        as: 'author',
        attributes: ['id', 'username', 'email', 'fullName', 'avatar']
      }
    ];
    
    // 如果有标签筛选
    if (tag) {
      include.push({
        model: Tag,
        as: 'tags',
        where: { name: tag },
        through: { attributes: [] }
      });
    } else {
      include.push({
        model: Tag,
        as: 'tags',
        through: { attributes: [] }
      });
    }
    
    // 查询文章总数
    const { count, rows } = await Post.findAndCountAll({
      where,
      include,
      order: [['publishedAt', 'DESC']], // 按发布时间倒序
      limit,
      offset: (currentPage - 1) * limit,
      distinct: true
    });
    
    // 计算总页数
    const totalPages = Math.ceil(count / limit);
    
    return res.status(200).json(success({
      posts: rows,
      pagination: {
        currentPage,
        pageSize: limit,
        totalItems: count,
        totalPages
      }
    }, '获取文章列表成功'));
  } catch (err) {
    console.error('获取文章列表失败:', err);
    return res.status(500).json(error('获取文章列表失败', 500));
  }
}; 